package com.cazor.dg.app;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.cazor.common.utils.StringUtils;
import com.cazor.dg.common.DgConstants;
import com.cazor.dg.domain.*;
import com.cazor.dg.service.IAdgLoginTokenHisService;
import com.cazor.dg.service.IDgRequestHisService;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class AppReqService {

    @Value("${dg.app.scheme:http}")
    private String scheme;

    @Value("${dg.app.ip}")
    private String ip;

    @Value("${dg.app.port}")
    private int port;

    @Value("${dg.app.username}")
    private String username;

    @Value("${dg.app.password}")
    private String password;

    @Value("${dg.app.timeout}")
    private int timeout;

    @Getter
    @Value("${dg.app.tokenEffectiveMinutes}")
    private int tokenEffectiveMinutes;
    @Resource
    private IDgRequestHisService requestHisService;

    @Resource
    private IAdgLoginTokenHisService loginTokenHisService;

    public JSONObject dLogin(){
        String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.D_LOGIN_PATH).build();
        JSONObject params = new JSONObject(2);
        params.put("username", username);
        params.put("password", password);
        HttpRequest request = HttpRequest.post(url).body(params.toString())
                .setConnectionTimeout(timeout).timeout(timeout);
        String respStr = null;
        JSONObject rtn = null;
        try {
            respStr = request.execute().body();
            rtn = JSON.parseObject(respStr);
        }catch (Exception e) {
            e.printStackTrace();
            rtn = this.createRtnJson(500, "鉴权请求异常"+e.getMessage(), false);
        }
        this.saveRequestHis(params.toString(), rtn.toString(), DgConstants.AppIds.D_LOGIN_ID,
                rtn.getInteger("code"), rtn.getBoolean("success"), rtn.getLong("timestamp"));
        return rtn;
    }


    /**
     * 新增 监测站 接口
     * @param monitorStation 监测站数据
     * @return
     */
    public JSONObject monitorStationAdd(DgMonitorStation monitorStation){
        JSONObject rtn = null;
        String token = this.getToken();
        JSONObject params = JSON.parseObject(JSON.toJSONString(monitorStation));
        params = this.removeAttr(params);
        if (StringUtils.isBlank(token)) {
            rtn = this.createRtnJson(201, "获取令牌为空", false);
        } else {
            String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.MONITOR_STATION_ADD_PATH).build();

            HttpRequest request = this.createHttpRequest(url, params, token);
            String respStr = null;
            try {
                respStr = request.execute().body();
                rtn = JSON.parseObject(respStr);
            } catch (Exception e) {
                rtn = this.createRtnJson(500, "新增 '监测站'请求异常" + e.getMessage(), false);
            }
        }
        this.saveRequestHis(params.toString(), rtn.toString(), DgConstants.AppIds.MONITOR_STATION_ADD_ID,
                rtn.getInteger("code"), rtn.getBoolean("success"), rtn.getLong("timestamp"));

        return rtn;
    }

    /**
     * 新增 监测内容 接口
     * @param dgDevDeviceInstance 监测内容数据
     * @return 结果
     */
    public JSONObject devDeviceInstanceAdd(DgDevDeviceInstance dgDevDeviceInstance) {
        JSONObject rtn = null;
        String token = this.getToken();
        JSONObject params = JSON.parseObject(JSON.toJSONString(dgDevDeviceInstance));
        params = this.removeAttr(params);
        if (StringUtils.isBlank(token)) {
            rtn = this.createRtnJson(201, "获取令牌为空", false);
        } else {
            String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.DEV_DEVICE_INSTANCE_ADD_PATH).build();

            HttpRequest request = this.createHttpRequest(url, params, token);
            String respStr = null;
            try {
                respStr = request.execute().body();
                rtn = JSON.parseObject(respStr);
            } catch (Exception e) {
                rtn = this.createRtnJson(500, "新增 '监测内容'请求异常" + e.getMessage(), false);
            }
        }
        this.saveRequestHis(params.toString(), rtn.toString(), DgConstants.AppIds.DEV_DEVICE_INSTANCE_ADD_ID,
                rtn.getInteger("code"), rtn.getBoolean("success"), rtn.getLong("timestamp"));

        return rtn;
    }

    /**
     * 新增 监测内容 接口
     * @param sensor 监测内容数据
     * @return 结果
     */
    public JSONObject deviceSensorAdd(DgDeviceSensor sensor) {
        JSONObject rtn = null;
        String token = this.getToken();
        JSONObject params = JSON.parseObject(JSON.toJSONString(sensor));
        params = this.removeAttr(params);
        if (StringUtils.isBlank(token)) {
            rtn = this.createRtnJson(201, "获取令牌为空", false);
        } else {
            String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.SENSOR_ADD_PATH).build();

            HttpRequest request = this.createHttpRequest(url, params, token);
            String respStr = null;
            try {
                respStr = request.execute().body();
                rtn = JSON.parseObject(respStr);
            } catch (Exception e) {
                rtn = this.createRtnJson(500, "新增 '传感器' 请求异常" + e.getMessage(), false);
            }
        }
        this.saveRequestHis(params.toString(), rtn.toString(), DgConstants.AppIds.SENSOR_ADD_ID,
                rtn.getInteger("code"), rtn.getBoolean("success"), rtn.getLong("timestamp"));

        return rtn;
    }

    public JSONObject resendDevDeviceParamData(JSONObject params) {
        JSONObject rtn = null;
        String token = this.getToken();
        if (CollectionUtil.isEmpty(params)) {
            return this.createRtnJson(202, "监测数据为空，不能提交数据", false);
        }
        // 转换 form 数据
        Map<String, Object> paramsMap = new HashMap<>(2);
        paramsMap.put("deviceInstancesData", params.getString("deviceInstancesData"));
        paramsMap.put("deviceParamData", params.getString("deviceParamData"));
        if (StringUtils.isBlank(token)) {
            rtn = this.createRtnJson(201, "获取令牌为空", false);
        } else {
            String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.INSERT_DEV_DEVICE_PARAM_DATA_PATH).build();
            HttpRequest request = this.createHttpRequest(url, token);
            String respStr = null;
            try {
                respStr = request.form(paramsMap).execute().body();
                rtn = JSON.parseObject(respStr);
            } catch (Exception e) {
                e.printStackTrace();
                rtn = this.createRtnJson(500, "新增 '监测数据' 请求异常" + e.getMessage(), false);
            }
        }
        return rtn;
    }

    /**
     * 新增 监测数据
     * @param params
     * @return
     */
    public JSONObject insertDevDeviceParamData(JSONObject params) {
        JSONObject rtn = null;
        String token = this.getToken();
        if (CollectionUtil.isEmpty(params)) {
            return this.createRtnJson(202, "监测数据为空，不能提交数据", false);
        }
        // 转换 form 数据
        Map<String, Object> paramsMap = new HashMap<>(2);
        paramsMap.put("deviceInstancesData", params.getString("deviceInstancesData"));
        paramsMap.put("deviceParamData", params.getString("deviceParamData"));
        if (StringUtils.isBlank(token)) {
            rtn = this.createRtnJson(201, "获取令牌为空", false);
        } else {
            String url = UrlBuilder.of().setScheme(scheme).setHost(ip).setPort(port).addPath(DgConstants.App.INSERT_DEV_DEVICE_PARAM_DATA_PATH).build();
            HttpRequest request = this.createHttpRequest(url, token);
            String respStr = null;
            try {
                respStr = request.form(paramsMap).execute().body();
                rtn = JSON.parseObject(respStr);
            } catch (Exception e) {
                e.printStackTrace();
                rtn = this.createRtnJson(500, "新增 '监测数据' 请求异常" + e.getMessage(), false);
            }
        }
        try {
            DgRequestHis his = this.saveRequestHis(params.toString(), rtn.toString(), DgConstants.AppIds.INSERT_DEV_DEVICE_PARAM_DATA_ID,
                    rtn.getInteger("code"), rtn.getBoolean("success"), rtn.getLong("timestamp"));
            rtn.put("requestHis", his);
        }catch (Exception e) {
            log.error("新增'监测数据' 写入请求调用数据表日志异常:{}", e.getMessage());
            rtn = this.createRtnJson(500, "新增'监测数据' 写入请求调用数据表日志异常:"+e.getMessage(), false);
        }
        return rtn;
    }

    private HttpRequest createHttpRequest(String url, JSONObject params, String token) {
        return HttpRequest.post(url).body(params.toString())
                .setConnectionTimeout(timeout).timeout(timeout).header("X-Access-Token", token);
    }

    public HttpRequest createHttpRequest(String url, String token) {
        return HttpRequest.post(url)
                .setConnectionTimeout(timeout).timeout(timeout).header("X-Access-Token", token);
    }

    public String getToken(){
        AdgLoginTokenHis his = loginTokenHisService.getLastLoginTokenHis(0);
        if (his == null) {
            return null;
        }
        return his.getToken();
    }

    /**
     * 保存 请求历史
     * @param req 请求参数
     * @param resp 返回参数
     * @param appId 请求的id
     * @param code 返回code
     * @param success 是否成功
     * @param timestamp 时间戳
     * @return 保存后的历史数据对象
     */
    public DgRequestHis saveRequestHis(String req, String resp, int appId, int code, boolean success, long timestamp) {
        DgRequestHis his = new DgRequestHis();
        his.setAppId(appId);
        his.setReq(req);
        his.setResp(resp);
        his.setCode(code);
        his.setSuccess(success?"1":"0");
        his.setCreateBy("sys");
        his.setCreateTime(DateTime.of(timestamp));
        his.setUpdateBy("");
        his.setUpdateTime(DateTime.now());
        try {
            requestHisService.save(his);
        }catch (Exception e) {
            log.error("数据库保存日志失败:{}", JSON.toJSONString(his));
        }
        return his;
    }

    public JSONObject createRtnJson(int code, String message, boolean isSuccess) {
        JSONObject rtn = new JSONObject(4);
        rtn.put("code", code);
        rtn.put("message", message);
        rtn.put("success", isSuccess);
        rtn.put("timestamp", System.currentTimeMillis());

        return rtn;
    }

    /**
     * 请求的参数 去除没有的属性
     * @param params 请求参数的json对象
     * @return 去除后的数据
     */
    private JSONObject removeAttr(JSONObject params) {
        params.remove("id");
        params.remove("status");
        params.remove("valid");
        params.remove("searchValue");
        params.remove("createBy");
        params.remove("createTime");
        params.remove("updateBy");
        params.remove("updateTime");
        params.remove("remark");
        params.remove("params");
        return params;
    }
}
